/*
 * cal.h
 *
 *  Created on: 2008-11-24
 *      Author: Administrator
 */

#ifndef CAL_H_
#define CAL_H_

#include "LinkedListStacks.h"
#include <iostream>
using namespace std;
template<class T>
class Calculator
{
private:
	LinkedStack<T> operand;
	void PuchOprd(const T & oprd);
	bool GetTwoOpr(T & oprd1, T & oprd2);
	void Compute(char op);
public:
	Calculator(){};
	~Calculator();
	void Clear(void);
	void Run(void);
};

template<class T>
Calculator<T>::~Calculator()
{
	operand.Clear();
}
template<class T>
void Calculator<T>::PuchOprd(const T & oprd)
{
	operand.Push(oprd);
}

template<class T>
bool Calculator<T>::GetTwoOpr(T & oprd1, T & oprd2)
{
	if(operand.IsEmpty())
		throw OutOfBounds();
	operand.Pop(oprd1);
	if(operand.IsEmpty())
		throw OutOfBounds();
	operand.Pop(oprd2);
	return true;
}

template<class T>
void Calculator<T>::Compute(char op)
{
	T oprd1, oprd2;
	if(GetTwoOpr(oprd1, oprd2))
	{
		switch(op)
		{
		case '+':
			operand.Push(oprd2 + oprd1);
			break;
		case '-':
			operand.Push(oprd2 - oprd1);
			break;
		case '*':
			operand.Push(oprd2 * oprd1);
			break;
		case '/':
			if(oprd1 == 0.0)
			{
				throw OutOfBounds();
				operand.Clear();
			}
			else
				operand.Push(oprd2 / oprd1);
			break;
		}
	}
	else
		operand.Clear();
}

template<class T>
void Calculator<T>::Run(void)
{
	char c;
	T new_oprd;
	while(cin>>c, c != '=')
	{
		switch(c)
		{
		case '+':
		case '-':
		case '*':
		case '/':
			Compute(c);
			break;
		default:
			cin.putback(c);
			cin>>new_oprd;
			PuchOprd(new_oprd);
			break;
		}
	}
	if(!operand.IsEmpty())
	{
		cout<<operand.GetTopData()<<endl;
	}
}

template<class T>
void Calculator<T>::Clear(void)
{
	operand.Clear();
}
#endif /* CAL_H_ */
